<?php

class Damages_Methods_Request_GetDamagesList extends Damages_Methods_Request {

  const FILTER_DATE_FROM = 'date_from';
  const FILTER_DATE_TO = 'date_to';
  const FILTER_VIN = 'vin';
  const FILTER_ID = 'id';
  const FILTER_LS_ID = 'ls_id';
  const FILTER_PERPETRATOR = 'perpetrat';
  const FILTER_PROCESS_TYPE = 'proc_type';
  const FILTER_BRAND = 'brand';
  const FILTER_COMMISION = 'commision';
  const FILTER_DAMAGE_DATE_FROM = 'd_date_fro';
  const FILTER_DAMAGE_DATE_TO = 'd_date_to';
  const FILTER_TRANSPORT_TYPE = 'trans_type';
  const FILTER_INVOICE_NO = 'invoice_no';
  const FILTER_DEALER_NO = 'deal_no';
  const FILTER_DEALER_NAME = 'deal_name';
  const FILTER_DEALER_REPORT_FROM = 'dea_d_from';
  const FILTER_DEALER_REPORT_TO = 'dea_d_to';
  const FILTER_DISCOUNT = 'discount';
  const FILTER_STATUS = 'status';

  /**
   *
   * @var Damages_Methods_Data_List_Filter_Use[] 
   */
  public $filters = array();

  /**
   *
   * @var int 
   */
  public $startIndex;

  /**
   *
   * @var int 
   */
  public $pageSize;

  /**
   *
   * @var string
   */
  public $sort;

  public function __construct($params) {
    parent::__construct($params);
    if ($params->filters)
      foreach ($params->filters->toArray() as $filter) {
        if (Damages_Auth::getInstance()->getUserFilter($filter->id) !== null)
          $this->filters[] = new Damages_Methods_Data_List_Filter_Use($filter);
      }
    $this->startIndex = $params->startIndex;
    $this->pageSize = $params->pageSize;
    $this->sort = $params->sort;
  }

  public function process() {
    $dbRows = $this->getDbRecords();
    $response = new Damages_Methods_Response_GetDamagesList(true);
    $response->setData($dbRows, $this->count);
    return $response;
  }

  private function getDbRecords() {
    $q = DamagesCarDamagesQuery::create();
    $q = $q
            ->useCarDamagesRelatedByIdQuery('CarDamagesRelatedByIdQuery')
            ->filterById(null, Criteria::ISNULL)
            ->endUse()
            ->leftJoinCarDamagesRelatedByRelatedCarDamage('CarDamagesRelatedByRelatedCarDamage')
            ->useCarDataQuery()
            ->joinDictBrands()
            ->leftJoinDealersRelatedByDealerId()
            ->endUse()
            ->leftJoinDictPerpetrators()
            ->leftJoinEstimatedBudgets()
            ->leftJoinInvoices()
            ->leftJoinUsersRelatedByLsId('UsersRelatedByLsId')
            ->leftJoinUsersRelatedByOlId('UsersRelatedByOlId')
            ->joinDictStatuses()
            ->joinProcessTypes();
    if ($this->filters)
      $q = $this->applyFilters($q);
    $q = $this->applyPermissionsFilters($q);
    $q = $q->groupById()->select(array('Id'));
    $q = $this->applySorting($q, true);
    $this->count = $q->count();
    $q
            ->limit($this->pageSize)
            ->offset($this->startIndex);
    $ids = $q->find();
    $resultQ = DamagesCarDamagesQuery::create();
    $resultQ = $resultQ
            ->useCarDamagesRelatedByIdQuery('CarDamagesRelatedByIdQuery')
            ->filterById(null, Criteria::ISNULL)
            ->endUse()
            ->leftJoinCarDamagesRelatedByRelatedCarDamage('CarDamagesRelatedByRelatedCarDamage')
            ->filterById($ids->toArray())
            ->useCarDataQuery()
            ->joinDictBrands()
            ->leftJoinDealersRelatedByDealerId()
            ->endUse()
            ->leftJoinDictPerpetrators()
            ->leftJoinEstimatedBudgets()
            ->leftJoinInvoices()
            ->leftJoinUsersRelatedByLsId('UsersRelatedByLsId')
            ->leftJoinUsersRelatedByOlId('UsersRelatedByOlId')
            ->joinProcessTypes()
            ->joinDictStatuses()
            ->with('CarData')
            ->with('DictBrands')
            ->with('DealersRelatedByDealerId')
            ->with('EstimatedBudgets')
            ->with('Invoices')
            ->with('ProcessTypes')
            ->with('UsersRelatedByLsId')
            ->with('UsersRelatedByOlId')
            ->with('DictStatuses')
            ->with('DictPerpetrators');
    $resultQ = $this->applySorting($resultQ);
    return $resultQ->find();
  }

  private function applyPermissionsFilters(DamagesCarDamagesQuery $q) {
    switch (Damages_Auth::getInstance()->getUser()->getPermissions()->getCode()) {
      case Damages_Auth::PERMISSION_SD:
        $dealersIds = array();
        foreach (Damages_Auth::getInstance()->getUser()->getUserDealerss() as $userDealer) {
          $dealer = $userDealer->getDealers();
          $dealersIds[] = $dealer->getId();
          if ($dealer->getDealersRelatedByParentId())
            $dealersIds[] = $dealer->getDealersRelatedByParentId()->getId();
//            foreach ($dealer->getDealersRelatedByParentId() as $parentDealer) {
//            }
        }

        $q->addCond('processFilter', DamagesProcessTypesPeer::CODE, DamagesProcessTypes::CODE_WAREHOUSE, Criteria::NOT_IN);
        $q->addCond('dealersFilter', DamagesCarDataPeer::DEALER_ID, $dealersIds, Criteria::IN);
        $q->addCond('dealersParentFilter', DamagesCarDataPeer::DEALER_PARENT_ID, $dealersIds, Criteria::IN);
//        $q->combine(array('dealersFilter', 'dealersParentFilter'), Criteria::LOGICAL_OR);
        $q->combine(array('dealersFilter', 'dealersParentFilter'), Criteria::LOGICAL_OR, 'dealersFilterGlobal');
        $q->addCond('processFilter', DamagesProcessTypesPeer::CODE, DamagesProcessTypes::CODE_WAREHOUSE, Criteria::NOT_EQUAL);
//        $q->addCond('statusesFilter', DamagesDictStatusesPeer::CODE, array(DamagesDictStatuses::CODE_NOT_ACCEPTED_WAITING_FOR_CAR_VALUE, DamagesDictStatuses::CODE_NOT_ACCEPTED_CLOSED, DamagesDictStatuses::CODE_NOT_ACCEPTED_OL, DamagesDictStatuses::CODE_NOT_ACCEPTED_SD), Criteria::NOT_IN);
        $q->addCond('statusesFilter', DamagesDictStatusesPeer::CODE, DamagesDictStatuses::CODE_NOT_ACCEPTED_OL, Criteria::NOT_EQUAL);
//        $q->combine(array('statusesFilter', 'dealersFilterGlobal'));
        $q->combine(array('processFilter', 'dealersFilterGlobal', 'statusesFilter'));
        break;
      case Damages_Auth::PERMISSION_OL:
        $q->filterByOlId(Damages_Auth::getInstance()->getUser()->getId());
        break;
      case Damages_Auth::PERMISSION_LS:
        break;
      default:
        break;
    }
    return $q;
  }

  private function applyFilters(DamagesCarDamagesQuery $q) {
    foreach ($this->filters as $filter) {
      $dbFilter = Damages_Auth::getInstance()->getUserFilter($filter->id);
      switch ($dbFilter->getCode()) {
        case self::FILTER_DATE_FROM:
          $q->filterByCreated($filter->value, Criteria::GREATER_EQUAL);
          break;
        case self::FILTER_DATE_TO:
          $q->filterByCreated($filter->value, Criteria::LESS_EQUAL);
          break;
        case self::FILTER_VIN:
          $q->where('CarData.Vin LIKE ?', sprintf('%%%s', $filter->value));
          break;
        case self::FILTER_ID:
          $q->filterById($filter->value);
          break;
        case self::FILTER_LS_ID:
          $q->filterByLsId($filter->value);
          break;
        case self::FILTER_PERPETRATOR:
          $q->filterByDictPerpetratorId($filter->value);
          break;
        case self::FILTER_PROCESS_TYPE:
          if (in_array(Damages_Auth::getInstance()->getUser()->getPermissions()->getCode(), array(Damages_Auth::PERMISSION_ADMIN, Damages_Auth::PERMISSION_LS))) {
            $q->addCond('basePTFilter', DamagesCarDamagesPeer::PROCESS_TYPE_ID, $filter->value, Criteria::IN);
            $q->addCond('noRelatedFilter', DamagesCarDamagesPeer::RELATED_CAR_DAMAGE, null, Criteria::ISNULL);
            $q->combine(array('basePTFilter', 'noRelatedFilter'), Criteria::LOGICAL_AND, 'noRelatedCD');
            $q->addCond('relatedDamageAvailable', 'CarDamagesRelatedByRelatedCarDamage.id', null, Criteria::ISNOTNULL);
            $q->addCond('relatedPTFilter', 'CarDamagesRelatedByRelatedCarDamage.process_type_id', $filter->value, Criteria::IN);
            $q->combine(array('relatedDamageAvailable', 'relatedPTFilter'), Criteria::LOGICAL_AND, 'relatedCD');
            $q->combine(array('noRelatedCD', 'relatedCD'), Criteria::LOGICAL_OR);
          }
          else
            $q->filterByProcessTypeId($filter->value);
          break;
        case self::FILTER_BRAND:
          $q->where(sprintf('DictBrands.Id IN(%s)', implode(',', $filter->value)));
          break;
        case self::FILTER_COMMISION:
          $q->where('CarData.ComissionNo = ?', $filter->value);
          break;
        case self::FILTER_DAMAGE_DATE_FROM:
          $q->filterByDamageDate($filter->value, Criteria::GREATER_EQUAL);
          break;
        case self::FILTER_DAMAGE_DATE_TO:
          $q->filterByDamageDate($filter->value, Criteria::LESS_EQUAL);
          break;
        case self::FILTER_TRANSPORT_TYPE:
          $q->where('DictPerpetrators.TransportType = ?', $filter->value);
          break;
        case self::FILTER_INVOICE_NO:
          $q->where('Invoices.Number = ?', $filter->value);
          break;
        case self::FILTER_DEALER_NO:
          $q->where('DealersRelatedByDealerId.Number = ?', $filter->value);
          break;
        case self::FILTER_DEALER_NAME:
          $q->where('DealersRelatedByDealerId.Name LIKE ?', '%' . $filter->value . '%');
          break;
        case self::FILTER_DEALER_REPORT_FROM:
          $q->filterByDealerReportDate($filter->value, Criteria::GREATER_EQUAL);
          break;
        case self::FILTER_DEALER_REPORT_TO:
          $q->filterByDealerReportDate($filter->value, Criteria::LESS_EQUAL);
          break;
        case self::FILTER_DISCOUNT:
          $q->where('EstimatedBudgets.DiscountFlag = ?', $filter->value);
          break;
        case self::FILTER_STATUS:
//          $q->where(sprintf('DictStatuses.Id IN(%s)', implode(',', $filter->value)));
          $q->filterByStatusId($filter->value);
          break;
        default:
          break;
      }
    }
    return $q;
  }

  private function applySorting(DamagesCarDamagesQuery $q, $groupByClause = false) {
    if (!$this->sort)
      return $q;
    $sortParams = explode(' ', $this->sort);
    $sortParam = $sortParams[0];
    $sortDirection = $sortParams[1] == 'ASC' ? Criteria::ASC : Criteria::DESC;
    switch ($sortParam) {
      case Damages_Methods_Data_CarDamageList::FIELD_CODE_ID:
        $q->orderById($sortDirection);
        break;
      case Damages_Methods_Data_CarDamageList::FIELD_CODE_CREATED:
        if ($groupByClause)
          $q->addGroupByColumn(DamagesCarDamagesPeer::CREATED);
        $q->orderByCreated($sortDirection);
        break;
      case Damages_Methods_Data_CarDamageList::FIELD_CODE_VIN:
        if ($groupByClause)
          $q->addGroupByColumn(DamagesCarDataPeer::VIN);
        $q->orderBy('CarData.Vin', $sortDirection);
        break;
      case Damages_Methods_Data_CarDamageList::FIELD_CODE_MODEL_NAME:
        if ($groupByClause)
          $q->addGroupByColumn(DamagesCarDataPeer::NAME);
        $q->orderBy('CarData.Name', $sortDirection);
        break;
      case Damages_Methods_Data_CarDamageList::FIELD_CODE_DEALER_NUMBER:
        if ($groupByClause)
          $q->addGroupByColumn(DamagesDealersPeer::NUMBER);
        $q->orderBy('DealersRelatedByDealerId.Number', $sortDirection);
        break;
      case Damages_Methods_Data_CarDamageList::FIELD_CODE_DEALER_NAME:
        if ($groupByClause)
          $q->addGroupByColumn(DamagesDealersPeer::NAME);
        $q->orderBy('DealersRelatedByDealerId.Name', $sortDirection);
        break;
      case Damages_Methods_Data_CarDamageList::FIELD_CODE_DAMAGE_TYPE:
        if ($groupByClause)
          $q->addGroupByColumn(DamagesProcessTypesPeer::NAME);
        $q->orderBy('ProcessTypes.Name', $sortDirection);
        break;
      case Damages_Methods_Data_CarDamageList::FIELD_CODE_PERPETRATOR:
        if ($groupByClause)
          $q->addGroupByColumn(DamagesDictPerpetratorsPeer::NAME);
        $q->orderBy('DictPerpetrators.Name', $sortDirection);
        break;
      case Damages_Methods_Data_CarDamageList::FIELD_CODE_DAMAGE_DATE:
        if ($groupByClause)
          $q->addGroupByColumn(DamagesCarDamagesPeer::DAMAGE_DATE);
        $q->orderByDamageDate($sortDirection);
        break;
      case Damages_Methods_Data_CarDamageList::FIELD_CODE_COMMISION:
        if ($groupByClause)
          $q->addGroupByColumn(DamagesCarDataPeer::COMISSION_NO);
        $q->orderBy('CarData.ComissionNo', $sortDirection);
        break;
      case Damages_Methods_Data_CarDamageList::FIELD_CODE_LS:
        if ($groupByClause)
          $q->addGroupByColumn('UsersRelatedByLsId.last_name');
        $q->orderBy('UsersRelatedByLsId.LastName', $sortDirection);
        break;
      case Damages_Methods_Data_CarDamageList::FIELD_CODE_BRAND:
        if ($groupByClause)
          $q->addGroupByColumn(DamagesDictBrandsPeer::NAME);
        $q->orderBy('DictBrands.Name', $sortDirection);
        break;
      case Damages_Methods_Data_CarDamageList::FIELD_CODE_TRANSPORT_TYPE:
        if ($groupByClause)
          $q->addGroupByColumn(DamagesDictPerpetratorsPeer::TRANSPORT_TYPE);
        $q->orderBy('DictPerpetrators.TransportType', $sortDirection);
        break;
      case Damages_Methods_Data_CarDamageList::FIELD_CODE_STATUS:
        if ($groupByClause)
          $q->addGroupByColumn(DamagesDictStatusesPeer::NAME);
        $q->orderBy('DictStatuses.Name', $sortDirection);
        break;
      case Damages_Methods_Data_CarDamageList::FIELD_CODE_INVOICE:
        if ($groupByClause)
          $q->addGroupByColumn(DamagesInvoicesPeer::NUMBER);
        $q->orderBy('Invoices.Number', $sortDirection);
        break;
      case Damages_Methods_Data_CarDamageList::FIELD_CODE_DEALER_REPORT_DATE:
        if ($groupByClause)
          $q->addGroupByColumn(DamagesCarDamagesPeer::DEALER_REPORT_DATE);
        $q->orderByDealerReportDate($sortDirection);
      case Damages_Methods_Data_CarDamageList::FIELD_CODE_MODIFIED:
        if ($groupByClause)
          $q->addGroupByColumn(DamagesCarDamagesPeer::MODIFIED);
        $q->orderByModified($sortDirection);
        break;
      default:
        break;
    }
    return $q;
  }

}